/***************************************************************************
 创建者: 华磊
 开始时间: 2018.4.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2017.5.29 类的具体实现代码编写

 ***************************************************************************/
#include "rfidsensor.h"
#include "domparser.h"
#include <QDebug>
RfidSensor::RfidSensor(QString configFileName)
{
    isReadRfidInfoOk = false;
    isSerialPortConnectOk = false;
    modbusMaster = NULL;

    rfidSerialPortInfo = new RFID_SerialPortInfo;
    readRfidInfo(configFileName);

    it = rfid_DeviceMap.begin();
    rfidFormerDeviceId = it.key();

    if( 1 == connectPort())
    {
        RFID_CardData cardData;
        cardData.cardData = '0';
        cardData.readCardTime = 0;
        for(int i = 0; i < rfid_DeviceMap.size(); i++)
        {
            mutex.lock();
            rfid_ReadTagMap.insert(rfid_DeviceMap.keys().at(i), cardData);
            mutex.unlock();
        }
        modbus_write_register(modbusMaster, D_RFID_MODE_REGISTER, D_RFID_MODE_MASTER_SLAVE_VALUE);

        timer.start(rfidSerialPortInfo->updatePeriod);
        QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(timeOut_slot()));
    }
}

bool RfidSensor::isReadRfidInfo()
{
    return isReadRfidInfoOk;
}

int RfidSensor::readRfidInfo(QString &infoReturn)
{
    DomParser domparser;
    qDebug() << " RfidSensor::readRfidInfo ===== read RfidInfo File:" << infoReturn;
    bool ok = domparser.openXml(infoReturn, QIODevice::ReadOnly);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== open RfidInfo File failed:" << infoReturn;
            return -1;
        }
    }

    QDomNode infoNode = domparser.findSubNode(domparser.getRootDomElement(), "SerialSetting", ok);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read SerialSetting FileNode failed:" << infoReturn;
            return -2;
        }
    }

    // 读取串口总线类型
    domparser.readXml(domparser.findSubNode(infoNode, "ModbusType", ok), rfidSerialPortInfo->ModbusType);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read ModbusType FileNode failed:" << infoReturn;
            return -3;
        }
    }

    //读取串口设备名
    domparser.readXml(domparser.findSubNode(infoNode, "serialDeviceName", ok),\
                      rfidSerialPortInfo->serialDeviceName);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read serialDeviceName FileNode failed:" << infoReturn;
            return -4;
        }
    }

    // 读取串口波特率
    domparser.readXml(domparser.findSubNode(infoNode, "baud", ok), rfidSerialPortInfo->baudRate);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read baud FileNode failed:" << infoReturn;
            return -5;
        }
    }

    // 读取串口校验位
    domparser.readXml(domparser.findSubNode(infoNode, "parity", ok), rfidSerialPortInfo->parity);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read parity FileNode failed:" << infoReturn;
            return -6;
        }
    }

    // 读取数据位
    domparser.readXml(domparser.findSubNode(infoNode, "data_bit", ok), rfidSerialPortInfo->dataBits);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read data_bit FileNode failed:" << infoReturn;
            return -6;
        }
    }

    // 读取停止位
    domparser.readXml(domparser.findSubNode(infoNode, "stop_bit", ok), rfidSerialPortInfo->stopBits);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read stop_bit FileNode failed:" << infoReturn;
            return -7;
        }
    }

    // 读取更新频率
    domparser.readXml(domparser.findSubNode(infoNode, "updatePeriod", ok), rfidSerialPortInfo->updatePeriod);
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug() << "RfidSensor::readRfidInfo ==== Read updatePeriod FileNode failed:" << infoReturn;
            return -8;
        }
    }

    QDomNode deviceNode = domparser.findSubNode(domparser.getRootDomElement(), "DeviceNode", ok );
    if( !ok )
    {
        if(D_IF_DEBUG)
        {
            qDebug()<<"RfidSensor::readRfidInfo ==== Read DeviceNode FileNode failed:: "\
                   << infoReturn;
        }
        return -9;
    }

    RFID_DeviceNode rfidDeviceNode;
    QDomNodeList domNodeList = deviceNode.childNodes();
    for(int i = 0; i < domNodeList.count(); i++)
    {
        domparser.readXml(domparser.findSubNode(domNodeList.at(i),"RFID_VendorId",ok), \
                          rfidDeviceNode.deviceVendorId);
        if( !ok )
        {
            if(D_IF_DEBUG)
            {
                qDebug() << "RfidSensor::readRfidInfo ==== Read RFID_VendorId FileNode failed:"\
                         << infoReturn;
            }
            return -1;
        }

        domparser.readXml(domparser.findSubNode(domNodeList.at(i),"deviceId",ok), \
                          rfidDeviceNode.deviceId);
        if( !ok )
        {
            if(D_IF_DEBUG)
            {
                qDebug() << "RfidSensor::readRfidInfo ==== Read deviceId FileNode failed:"\
                         << infoReturn;
            }
            return -1;
        }

        mutex.lock();
        rfid_DeviceMap.insert(rfidDeviceNode.deviceId,rfidDeviceNode);
        mutex.unlock();
    }
    domparser.closeXml(true);
    isReadRfidInfoOk = true;
    return 1;
}

int RfidSensor::connectPort()
{
    if(isReadRfidInfoOk == false)
    {
        return -1;
    }

    if(E_MODBUS_TYPE_TCP_RFID == rfidSerialPortInfo->ModbusType)
    {
        return -1;
    }
    else if(E_MODBUS_TYPE_RTU_RFID == rfidSerialPortInfo->ModbusType)
    {
        modbusMaster =modbus_new_rtu(rfidSerialPortInfo->serialDeviceName.toStdString().data(),
                                     rfidSerialPortInfo->baudRate,
                                     (*rfidSerialPortInfo->parity.toStdString().data()),
                                     rfidSerialPortInfo->dataBits,
                                     rfidSerialPortInfo->stopBits);

         modbus_set_slave(modbusMaster,it.key());
         if (modbus_connect(modbusMaster) == -1)
         {
              qDebug()<<"Modbus485Driver::connectPort connect failed";
              modbus_free(modbusMaster);
              modbusMaster=NULL;
              return -1;
         }
         else
         {
              qDebug()<<"connect success";
              isSerialPortConnectOk=true;
              modbus_set_response_timeout(modbusMaster, 0, 500000);
              return 1;
         }
    }

    return -1;
}

void RfidSensor::timeOut_slot()
{
   readTag();
}

int RfidSensor::readTag()
{
    if(isReadRfidInfoOk == false)
    {
        return -1;
    }
    if(1 != checkModbusMaster())
    {
        return -1;
    }

    switch (it.value().deviceVendorId) {
        case E_VENDOR_ID_JIAN_YONG:
        {
            int returnKey = readTagVendorId();
            if(returnKey == 1)
            {
                mutex.lock();
                if(it.key() == rfid_DeviceMap.lastKey() )
                {
                    it = rfid_DeviceMap.begin();
                }
                else
                {
                    it++;
                }
                mutex.unlock();
                return 1;
            }
            break;
        }
    }

    return -1;
}

int RfidSensor::readTagVendorId()
{
    uint16_t receiveData[MODBUS_MAX_ADU_LENGTH] = {0};
    RFID_CardData cardData;
    long tagData;
    int readTime;
    unsigned char highByte = 0xff;
    unsigned char lowByte = 0xff;
    int resultKey = modbus_read_registers(modbusMaster,\
                                          D_RFID_READ_TAG_REGISTER,\
                                          D_RFID_TAG_REGISTERS_NUMBER, \
                                          receiveData);

    if(resultKey != -1)
    {
        highByte = highByte & receiveData[0];
        tagData = highByte;
        tagData = (tagData << 16) | receiveData[1];
        tagData = (tagData << 16) | receiveData[2];

        readTime = lowByte & receiveData[6];
        cardData.readCardTime = readTime*0.2;
        cardData.cardData = QString("%1").arg(tagData);

        mutex.lock();
        rfid_ReadTagMap[it.key()] = cardData;
        mutex.unlock();
        isSerialPortConnectOk = true;
        return 1;
    }
    else
    {
        isSerialPortConnectOk = false;
        return -1;
    }

    return -1;
}

int RfidSensor::getCurrentTagData(int deviceId, QString &valueOut, double &readCardTime)
{
    mutex.lock();
    if(rfid_DeviceMap.keys().contains(deviceId) == false)
    {
        mutex.unlock();
        valueOut='0';
        readCardTime=0;
        qDebug() << "RfidSensor::getCurrentTagData ==== The deviceId parameter is wrong!";
        return -1;
    }
    mutex.unlock();

    if(isSerialPortConnectOk == false)
    {
        valueOut='0';
        readCardTime=0;
        qDebug() << "RfidSensor::getCurrentTagData ==== The serialPort Connect failed!";
        return -1;
    }

    if(isReadRfidInfoOk == false)
    {
        valueOut='0';
        readCardTime=0;
        return -1;
    }
    if(1 != checkModbusMaster())
    {
        valueOut='0';
        readCardTime=0;
        return -1;
    }

    mutex.lock();
    readCardTime = rfid_ReadTagMap.value(deviceId).readCardTime;
    mutex.unlock();
    if(readCardTime == 0.0)
    {
        mutex.lock();
        valueOut = rfid_ReadTagMap.value(deviceId).cardData;
        mutex.unlock();
        return 1;
    }
    else
    {
        valueOut = '0';
        return 0;
    }

    return -1;
}

int RfidSensor::checkModbusMaster()
{
    if(E_MODBUS_TYPE_TCP_RFID == rfidSerialPortInfo->ModbusType)
    {
        return -1;
    }
    if(NULL==modbusMaster && -1==it.key())
    {
        int returnKey;
        returnKey=connectPort();
        if(1==returnKey)
        {
           rfidFormerDeviceId=it.key();
           return 1;
        }
        else
        {
           return -1;
        }
    }
    else if(it.key() !=rfidFormerDeviceId)
    {
        int returnKey;
        modbus_close(modbusMaster);
        modbus_free(modbusMaster);
        returnKey=connectPort();
        if(1==returnKey)
        {
            rfidFormerDeviceId=it.key();
            return 1;
        }
        else
        {
            return -2;
        }
    }
    return 1;
}

unsigned int RfidSensor::CRC_MB_RFID(unsigned char *cBuffer,unsigned int iBuflen)
{
    unsigned int i, j;
    unsigned int wPolynom = 0xa001;
    unsigned int wCrc = 0xffff;
    for(i = 0; i<iBuflen; i++)
    {
        wCrc ^= cBuffer[i];
        for(j = 0; j <8 ;j++)
        {
            if(wCrc & 0x0001)
            {
                wCrc = (wCrc >> 1) ^ wPolynom;
            }
            else
            {
                wCrc = wCrc >> 1;
            }
        }
    }
    return wCrc;
}
